package com.linden.std.controller.admin;

import com.linden.std.constant.CommonConstant;
import com.linden.std.domain.dto.ChangePasswordRequest;
import com.linden.std.domain.dto.LoginRequest;
import com.linden.std.domain.dto.RefreshTokenRequest;
import com.linden.std.domain.vo.LoginResponse;
import com.linden.std.domain.vo.TokenResponse;
import com.linden.std.domain.vo.UserVO;
import com.linden.std.result.Result;
import com.linden.std.service.auth.LocalAuthService;
import com.linden.std.service.auth.LoginSecurityService;
import com.linden.std.Utils.UserContextUtil;
import com.linden.std.util.RSAUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.Map;

/**
 * 认证控制器
 */
@Slf4j
@RestController
@RequestMapping("/auth")
@Api(tags = "认证管理")
public class AuthController {

    @Autowired
    private LocalAuthService authService;
    
    @Autowired
    private LoginSecurityService loginSecurityService;

    @GetMapping("/publicKey")
    @ApiOperation("获取RSA公钥")
    public Result<String> getPublicKey(HttpServletRequest request) {
        try {
            // 生成RSA密钥对
            Map<String, Object> keyMap = RSAUtils.genKeyPair();
            
            // 将私钥存储到Session中
            HttpSession session = request.getSession();
            String privateKey = RSAUtils.getPrivateKey(keyMap);
            session.setAttribute(RSAUtils.SESSION_PRIVATE_KEY, privateKey);
            log.info("RSA密钥对生成成功，私钥已存储到Session中");
            
            // 返回公钥给前端
            String publicKey = RSAUtils.getPublicKey(keyMap);
            return Result.success(publicKey);
            
        } catch (Exception e) {
            log.error("获取RSA公钥失败", e);
            return Result.error("获取公钥失败: " + e.getMessage());
        }
    }

    @PostMapping("/login")
    @ApiOperation("用户登录")
    public Result<LoginResponse> login(@Validated @RequestBody LoginRequest request, HttpServletRequest httpRequest) {
        try {
            // 从 Session 获取私钥
            HttpSession session = httpRequest.getSession(false);
            if (session == null) {
                log.warn("登录失败：会话不存在，请先获取公钥");
                return Result.error(400, "请先获取公钥");
            }
            
            String privateKey = (String) session.getAttribute(RSAUtils.SESSION_PRIVATE_KEY);
            if (privateKey == null) {
                log.warn("登录失败：私钥不存在，请先获取公钥");
                return Result.error(400, "请先获取公钥");
            }
            
            // 使用私钥解密密码
            String decryptedPassword;
            try {
                decryptedPassword = RSAUtils.decryptDataOnJava(request.getPassword(), privateKey);
                log.info("密码解密成功，用户名: {}", request.getUsername());
            } catch (Exception e) {
                log.error("密码解密失败，用户名: {}", request.getUsername(), e);
                return Result.error(400, "密码解密失败，请重新获取公钥");
            }
            
            // 创建新的登录请求对象，使用解密后的密码
            LoginRequest decryptedRequest = new LoginRequest();
            decryptedRequest.setUsername(request.getUsername());
            decryptedRequest.setPassword(decryptedPassword);
            decryptedRequest.setClientIp(request.getClientIp());
            
            // 调用原有的登录逻辑
            LoginResponse response = authService.login(decryptedRequest, httpRequest);
            
            // 清除私钥（安全考虑）
            session.removeAttribute(RSAUtils.SESSION_PRIVATE_KEY);
            log.info("登录成功，已清除Session中的私钥，用户名: {}", request.getUsername());
            
            return Result.success(response);
            
        } catch (Exception e) {
            log.error("登录异常，用户名: {}", request.getUsername(), e);
            return Result.error("登录失败: " + e.getMessage());
        }
    }

    @PostMapping("/refresh")
    @ApiOperation("刷新Token")
    public Result<TokenResponse> refreshToken(@RequestBody RefreshTokenRequest request) {
        TokenResponse response = authService.refreshToken(request.getRefreshToken());
        return Result.success(response);
    }

    @PostMapping("/logout")
    @ApiOperation("用户登出")
    public Result<Void> logout(HttpServletRequest request) {
        String token = extractToken(request);
        authService.logout(token, request);
        return Result.success();
    }

    @GetMapping("/userinfo")
    @ApiOperation("获取当前用户信息")
    public Result<UserVO> getUserInfo(HttpServletRequest request) {
        // 添加调试信息
        String token = extractToken(request);
        log.info("获取用户信息 - Token: {}", token != null ? "存在" : "不存在");
        
        UserVO userVO = UserContextUtil.getUser();
        log.info("获取用户信息 - UserVO: {}", userVO != null ? "存在" : "不存在");
        
        if (userVO == null) {
            log.warn("用户上下文为空，可能原因：1.未传Token 2.Token无效 3.请求路径在白名单中");
        }
        
        return Result.success(userVO);
    }

    @PostMapping("/change-password")
    @ApiOperation("修改密码")
    public Result<Void> changePassword(@Validated @RequestBody ChangePasswordRequest request) {
        authService.changePassword(request);
        return Result.success();
    }
    
    @GetMapping("/login-security-status")
    @ApiOperation("获取登录安全状态")
    public Result<Map<String, Object>> getLoginSecurityStatus(
            @RequestParam String account, 
            HttpServletRequest request) {
        try {
            String clientIp = getClientIp(request);
            Map<String, Object> status = new HashMap<>();
            
            // 账户状态
            boolean accountLocked = loginSecurityService.isAccountLocked(account);
            status.put("accountLocked", accountLocked);
            
            if (accountLocked) {
                long remainingTime = loginSecurityService.getAccountLockRemainingTime(account);
                status.put("accountLockRemainingTime", remainingTime);
                status.put("accountLockRemainingMinutes", remainingTime / 60);
            } else {
                int remainingAttempts = loginSecurityService.getRemainingAttempts(account);
                status.put("remainingAttempts", remainingAttempts);
            }
            
            // IP状态
            boolean ipLocked = loginSecurityService.isIpLocked(clientIp);
            status.put("ipLocked", ipLocked);
            
            if (ipLocked) {
                long remainingTime = loginSecurityService.getIpLockRemainingTime(clientIp);
                status.put("ipLockRemainingTime", remainingTime);
                status.put("ipLockRemainingMinutes", remainingTime / 60);
            }
            
            status.put("clientIp", clientIp);
            
            return Result.success(status);
            
        } catch (Exception e) {
            log.error("获取登录安全状态失败", e);
            return Result.error("获取安全状态失败: " + e.getMessage());
        }
    }

    private String extractToken(HttpServletRequest request) {
        String token = request.getHeader(CommonConstant.TOKEN_HEADER);
        if (StringUtils.isNotBlank(token) && token.startsWith(CommonConstant.TOKEN_PREFIX)) {
            return token.substring(CommonConstant.TOKEN_PREFIX.length());
        }
        return null;
    }
    
    private String getClientIp(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("X-Real-IP");
        }
        if (StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}